<template>
  <div class="init-container">
    <div class="mask-container" v-if="isMask"></div>
    <Drawer
      :title="$srv.getI18nByValue(title)"
      :placement="placement"
      :closable="true"
      v-model="isShow"
      :mask="false"
      draggable
      :width="width"
      @on-resize-width="onDrawerWidth"
      ref="drawer"
    >
      <div class="body-main">
        <div class="grid-container">
          <o-base-grid
            :compBoxInfo="GT_compBoxInfo"
            :config="config"
            :regCustEventName="regCustEventName"
            @on-cell-dblclick="onCellDblclick"
            @on-row-change="onRowChange"
          />
        </div>
        <div class="graph-container">
          <div :id="G_pageID" class="full-width-height" />
        </div>
      </div>
    </Drawer>
  </div>
</template>

<script lang="ts">
import { N_oBaseGrid } from '@/types';
import {
  G6,
  graphCfg,
  GraphOptions,
  ifs,
  T_srv,
  ts,
  Tsrv,
  vue
} from './config';

@T_srv.comp({
  components: {}
})
export default class oOpenGraphData extends vue {
  /* 父组件compBoxInfo */
  @T_srv.prop({
    required: false,
    type: Object,
    default: null
  })
  compBoxInfo: ifs.I_compBoxInfo;

  @T_srv.prop({
    required: false,
    type: String,
    default: '查询'
  })
  title: string;

  @T_srv.prop({
    required: false,
    type: String,
    default: 'left',
    validator: v => /^left$|^right$/.test(v)
  })
  placement: string;

  @T_srv.prop({
    required: false,
    type: String,
    default: '800px',
    validator: v => /^\d+$|^\d+px$/.test(v)
  })
  width: string;

  @T_srv.prop({
    required: true,
    type: Object
  })
  config: any; // baseGrid

  @T_srv.ref(`drawer`) G_drawer: any;

  /* 组件名 */
  private G_compName: string = 'oOpenGraphData';

  /* 组件箱信息对象 */
  private GT_compBoxInfo: ifs.I_compBoxInfo;

  /* 组件箱对象 */
  private GT_compBox: ifs.I_compBox;

  /* 组件箱识别ID */
  private G_compID: string;

  private isShow: boolean = false;

  private G_pageID: string; // 画布ID

  private G_graphCfg: GraphOptions = graphCfg();

  private G_graph: any;

  private G_data: Array<any> = [];

  private tableName: string;

  public isMask: boolean = false;

  // 不接收标准组件事件
  public regCustEventName: Array<N_oBaseGrid.I_regCustEventName | string> = [];

  get G_isShow(): boolean {
    return this.isShow;
  }

  set G_isShow(v: boolean) {
    if (this.isShow !== v) {
      this.isShow = v;
    }
  }

  created() {
    this.tableName = this.config.name;
    this.G_pageID = `${Tsrv.utils.custUUID(5, 16)}-graph-container`;
    this.G_compID = Tsrv.utils.getGUID();
    /* 如果外部有传入组件信息 */
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox = new ts.T_compBox(this.G_compID); // 使用本地实例
    } else {
      this.G_compID = this.compBoxInfo.compID;
      this.GT_compBox = this.compBoxInfo.TcompBox;
    }
    this.GT_compBoxInfo = { compID: this.G_compID, TcompBox: this.GT_compBox };

    const defListener = {
      receive: {
        source: this.config.name,
        target: Tsrv.utils.custUUID(6) // 使接收事件无效
      }
    };
    const custDefListener = this.config?.messageConfig?.custDefListener;
    if (!Tsrv.utils.noValue(custDefListener)) {
      let isNull = true;
      Object.keys(custDefListener).forEach(key => {
        if (!Tsrv.utils.noValue(custDefListener[key])) {
          isNull = false;
          if (Array.isArray(custDefListener[key])) {
            custDefListener[key].forEach(ele => {
              this.regCustEventName.push({
                receive: {
                  source: ele,
                  target: Tsrv.utils.custUUID(6) // 使接收事件无效
                }
              });
            });
          } else if (typeof custDefListener[key] === 'string') {
            this.regCustEventName.push(custDefListener[key]);
          } else {
            throw new Error(`无法识别的事件监听[${custDefListener[key]}]`);
          }
        }
      });
      if (isNull) {
        this.regCustEventName.push(defListener);
      }
    } else {
      // 拦截接收事件
      this.regCustEventName.push(defListener);
    }

    if (!Tsrv.utils.noValue(this.config?.messageConfig)) {
      const emitActions = this.config.messageConfig?.emitActions;
      // 发送事件拦截
      if (!Tsrv.utils.noValue(emitActions)) {
        emitActions.search.forEach(ele => {
          // 拦截发送事件
          this.regCustEventName.push({
            send: {
              source: ele.toID,
              target: Tsrv.utils.custUUID(6) // 使发送事件无效
            }
          });
        });
      }
    }
  }

  mounted() {
    /* 向父组件发送实例 */
    this.$emit('compBoxInfo', this.GT_compBoxInfo);
    this.GT_compBox.addCompMergeName(this.G_compID, this.G_compName, this);
    this.$nextTick(this.createGraph);
  }

  destroyed() {
    /* 注册组件销毁 */
    this.GT_compBox.removeCompMergeName(this.G_compID, this.G_compName);

    /* 如果父组件传入的compBoxInfo则删除本文件产生的引用,反之是本组件产生的ID统一删除 */
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox.removeCompsWithCompID(this.G_compID);
    } else {
      this.GT_compBox.removeCompsMergeName(this.G_compID, [
        `'${this.G_compName}'`
      ]);
    }
    this.G_graph.destroy();
  }

  createGraph() {
    setTimeout(() => {
      this.G_graphCfg.height =
        document.getElementById(this.G_pageID).scrollHeight || 400;
      this.G_graphCfg.width =
        document.getElementById(this.G_pageID).scrollWidth || 490;
      this.G_graphCfg.container = this.G_pageID;
      this.G_graph = new G6.Graph(this.G_graphCfg);
    }, 10);
  }

  @T_srv.emit('on-cell-dblclick')
  onCellDblclick(e: any) {
    this.G_isShow = false;
    this.GT_compBox.getCompMergeName(
      this.G_compID,
      'oGraph'
    ).isShowNodeForm = false;
  }

  @T_srv.emit('on-row-change')
  onRowChange(e: any) {
    this.loadGraph(e.data.to);
  }

  public loadGraph(e: any): Promise<boolean> {
    return new Promise(resolve => {
      const gpfd = new ts.T_getPartDataArg();
      gpfd.setFilter({
        $and: [
          { source_table: { $eq: this.tableName } },
          { [Tsrv.globalVar.fieldName.masterBillId]: { $eq: e.row.id ?? '-1' } }
        ]
      });
      // 规定的表名  mongo xcsys._sys_grpah
      // gpfd.setFunName(Tsrv.globalVar.tableName.MONGO_GRAPH);
      // gpfd.setTableName(Tsrv.globalVar.tableName.MONGO_GRAPH);
      // gpfd.setDbType(Tsrv.globalVar.dbType.MONGO);
      gpfd.setFunName(Tsrv.globalVar.tableName.MYSQL_GRAPH);
      gpfd.setTableName(Tsrv.globalVar.tableName.MYSQL_GRAPH);
      gpfd.setDbType(Tsrv.globalVar.dbType.MYSQL);
      gpfd.setLang(this.$i18n.locale);
      gpfd.setPage(1, 10);
      gpfd.setRule({} as ifs.I_rule);

      Tsrv.getData(gpfd).then(([b, res, _, m]) => {
        if (!m || !res.success) {
          this.$msg(m ?? res.msg);
        }
        this.G_graph.clear();
        if (res.data.total > 0) {
          const rec = Tsrv.utils.clone(res.data.rows[0], true);
          const graph =
            typeof rec['f_data'] === 'string'
              ? JSON.parse(rec['f_data'])
              : rec['f_data'];
          delete rec['_XID'];
          delete rec['_file_info_id_'];
          delete rec['_sort_'];
          this.setGraphData(graph);
        }
      });
    });
  }

  onCellClick(e: any) {
    e.row.id && this.setGraphData(e.row.id);
  }

  setGraphData(data: any) {
    this.G_graph.read(data);
    this.G_graph.fitView();
  }

  setDisplay(b: boolean) {
    this.G_isShow = b;
  }

  onDrawerWidth(e) {
    const self = this;
    setTimeout(() => {
      let h: number = document.getElementById(this.G_pageID).clientHeight;
      let w: number = document.getElementById(this.G_pageID).clientWidth;
      if (w - 10 < 0) {
        w = 0;
      }
      if (h - 10 < 0) {
        h = 0;
      }
      self.G_graph.changeSize(w, h);
      self.G_graph.fitView();
    }, 10);
  }

  // // 自定义事件 这里只用来作拦截组件间默认baseGrid事件
  // getregCustEvent(): Array<N_oBaseGrid.I_regCustEventName> {
  //   return this.regCustEventName;
  // }
}
</script>
<style lang="scss" scoped>
::v-deep .ivu-drawer-body {
  padding: 0px;
}
::v-deep .vxe-toolbar {
  border-top: 2px solid #f4f4f4;
  padding: 6px;
}
::v-deep .vxe-button {
  border: 1px solid #fff;
}
::v-deep .ivu-drawer-wrap .ivu-drawer {
  height: calc(100vh - 42px);
  top: 42px;
}
::v-deep .ivu-drawer-wrap {
  z-index: 103;
}

.graph-container {
  flex: auto;
  flex-shrink: 1;
  order: 2;
  overflow: auto;
}
.grid-container {
  flex-shrink: 0;
  height: calc(100vh / 2);
  order: 1;
}
.body-main {
  height: 100%;
  display: flex;
  flex-direction: column;
}
</style>
